Priority Queue

우선 순위 큐
'우선 순위’를 가지는 데이터를 저장하는 큐
데이터를 꺼낼 때 우선 순위가 높은 데이터가 가장 먼저 나온다는 특징이 있다.

우선순위 큐는 운영체제의 작업 스케줄링, 정렬, 네트워크 관리 등의 다양한 기술에 적용되고 있다.

우선순위 큐는 선형적인 형태를 가지고 있지만, 우선순위 큐는 트리(Tree) 구조로 보는 것이 합리적이다.
일반적으로 우선순위 큐는 최대 힙을 이용해 구현
최대 힙(Max Heap)
부모 노드가 자식 노드보다 값이 큰 완전 이진 트리(루트 노드가 가장 큰 값을 가진다.)
우선순위 큐의 삽입
삽입할 원소는 완전 이진 트리를 유지하는 형태로 순차적으로 삽입
삽입 이후 루트 노드까지 거슬러 올라가면서 최대 힙을 구성[상향식] (logN 만큼 소모)
우선순위 큐의 삭제
삭제를 할 때는 루트 노드를 삭제하고, 가장 마지막 원소를 루트 노드의 위치로 옮겨준다.
삭제 이후 리프 노드까지 내려가면서 최대 힙을 구성 [하향식]

부모의 인덱스는 자식의 인덱스에서 2로 나누었을 때의 몫이다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 10000
void swap(int *a, int *b){
int temp=*a;
*a=*b;
*b=temp;
}
typedef struct{
int heap[MAX_SIZE];
int count;
}priorityQueue;
void push(priorityQueue *pq, int data){
if(pq->count>=MAX_SIZE)return;
pq->heap[pq->count]=data;
int now=pq->count;
int parent=(pq->count-1)/2;
while(now>0 && pq->heap[now] > pq->heap[parent]){
swap(&pq->heap[now], &pq->heap[parent]);
now=parent;
parent=(parent-1)/2;
}
pq->count++;
}
int pop(priorityQueue *pq){
if(pq->count<=0)return -9999;
int res=pq->heap[0];
pq->count--;
pq->heap[0]=pq->heap[pq->count];
int now =0, leftChild=1, rightChild=2;
int target=now;
while(leftChild<pq->count){
if(pq->heap[target]<pq->heap[leftChild])target=leftChild;
if(pq->heap[target]<pq->heap[rightChild] && rightChild < pq->count) target=rightChild;
if(target==now)break;
else{
swap(&pq->heap[now], &pq->heap[target]);
now=target;
leftChild=now*2+1;
rightChild=now*2+2;
}
}
return res;
}
int main(void){
int n, data;
scanf("%d", &n);
priorityQueue pq;
pq.count=0;
for(int i=0;i<n;i++){
scanf("%d", &data);
push(&pq, data);
}
for(int i=0;i<n;i++){
int data=pop(&pq);
printf("%d ", data);
}
system("pause");
return 0;
}
우선순위 큐의 삽입과 삭제는 O(logN)의 시간 복잡도를 가진다.
우선순위 큐를 이용한 정렬은 O(NlogN)의 시간 복잡도를 가진다.